package org.jeecg.common.aspect;

import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.time.StopWatch;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.MakeFriendsBaseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;

import lombok.extern.slf4j.Slf4j;


@Slf4j
@Aspect
@Component
@EnableAspectJAutoProxy
public class ControllerMethodAspect {
    private static final String MESSAGE_METHOD_NEW_BUILDER = "newBuilder";

    private static final ConcurrentHashMap<Class, Logger> LOGGER_HOLDER = new ConcurrentHashMap<>();

    @Pointcut("@annotation(org.jeecg.common.aspect.ControllerMethodCheck)")
    public void grpcMethodCheck() {

    }

    @Around(value = "grpcMethodCheck()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        StopWatch stopwatch = new StopWatch();
        initKsLogId();

        Object[] args = pjp.getArgs();
        String className = pjp.getTarget().getClass().getSimpleName();
        String methodName = pjp.getSignature().getName();
        Logger logger = getLogger(pjp);

        try {
            Object result = pjp.proceed();
            try {
                logger.info("success to {}#{} args:{} response:{} rt:{}", className, methodName,
                        JSON.toJSON(args[0]),
                        JSON.toJSON(result), stopwatch.getTime());
            } catch (Exception e) {

            }
            return result;
        } catch (MakeFriendsBaseException logisticsBaseException) {
            try {
                log.error("failed to {}#{} args:{}, error:{}", className, methodName,
                        JSON.toJSON(args[0]),
                        logisticsBaseException.getMessage(),
                        logisticsBaseException);
            } catch (Exception e) {

            }

            // 封装异常返回
            return Result.error(logisticsBaseException.getCode(), logisticsBaseException.getMsg());
        } catch (Throwable ex) {
            log.error("failed to {}#{} args:{}", className, methodName, JSON.toJSON(args[0]), ex);
            // 封装异常返回
            return Result.error("抱歉~, 系统异常，请重试");
        }
    }

    private void initKsLogId() {
        // 按道理都会有ksLogId，但是客服平台没有接入ksLogId，面向kibana设置个ksLogId
        //        if (StringUtils.isBlank(CommonWebScope.ksLogId())) {
        //            CommonWebScope.setKsLogId(UUID.randomUUID().toString());
        //        }
    }

    private Logger getLogger(JoinPoint jp) {
        Class declaringType = jp.getSignature().getDeclaringType();
        Logger logger = LOGGER_HOLDER.get(declaringType);
        // 可能还是会有并发覆盖，但是没影响
        if (logger == null) {
            logger = LoggerFactory.getLogger(declaringType);
            LOGGER_HOLDER.put(declaringType, logger);
        }
        return logger;
    }

}
